FEXP Solver  1.0.0.0
FEXPSolver.h
Go to the documentation of this file.
1 // © FEXP, FEXPEnterprise Solver, Ing. Vaclav Rek
3 // Manager of a numerical simulation process.
4 // Compiler must support C++ ver.14 and later
6 #ifndef _CFEXPSOLVER_H_
7 #define _CFEXPSOLVER_H_
8 #include "FEXPCommon.h"
9 #include "FEXPElement.h"
10 #include "FEXPConcurency.h"
11 #include "FEXPTopologieKDTree.h"
12 #include "FEXPModelBuilder.h"
13 #include "FEXPCalculation.h"
14 #include "FEXPNetworkInterface.h"
15 
22 
25 {
26 public:
28  : _builder(builder), _exporter(exporter) { }
29  virtual ~ICFEXPSolverBase() { }
30 
31  // pure virtual member functions
34  virtual void Start() = 0;
37  virtual void End() = 0;
38  // adding and removing model
39  virtual void AddModel(const t_ModelData & data) = 0;
40  virtual void RmvModel(const std::string & key ) = 0;
41  // current time step dt
42  virtual t_fexpcommon_ct GetCurrentDt() = 0;
43  virtual void SetCurrentDt(t_fexpcommon_ct dt) = 0;
44  // serialized data
46  virtual void SetSerializedData(Ptr<t_SerializedData> data) = 0;
47 protected:
51 
54  check_node(const std::vector<t_fexpcommon_ct> & min_bound, const std::vector<t_fexpcommon_ct> & max_bound);
55 private:
56  // [no private members ] -----------------------------
57 };
58 
65 // primary template
66 template<typename TValue, typename Enable = void>
70 template<typename TExpCalc>
72  <TExpCalc, typename std::enable_if<std::is_base_of<ICFEXPExplicitCalcBase, TExpCalc>::value>::type>
73  : public ICFEXPSolverBase
74 {
75 public:
77  virtual ~CFEXPSequentialSolver() { }
78 
79  // override base virtual functions
80  virtual void Start() override;
81  virtual void End () override { FEXPCOMMON_NOT_IMPLEMENTED_EX; }
82  // adding and removing model
83  virtual void AddModel(const t_ModelData & data) override { FEXPCOMMON_NOT_IMPLEMENTED_EX; }
84  virtual void RmvModel(const std::string & key ) override { FEXPCOMMON_NOT_IMPLEMENTED_EX; }
85  // current time step dt
88  // serialized data
91 protected:
92  // [no protected members] -----------------------------
93 private:
94  Ptr<TExpCalc> _calculator;
95 };
96 
97 //--------------------------------------------------------------------------------------
98 template<typename TExpCalc>
101  : ICFEXPSolverBase(builder, exporter),
102  _calculator(CFEXPDataManager<TExpCalc>::SafeAllocInstance(builder->GetModelContainer(), _exporter,
103  [this] { update_topology_map_for_contact(); }, [this](auto in1, auto in2) { return check_node(in1, in2); })) { }
104 //--------------------------------------------------------------------------------------
105 
106 //--------------------------------------------------------------------------------------
107 template<typename TExpCalc>
109 ::Start()
110 //--------------------------------------------------------------------------------------
111 {
112  try
113  {
114  auto result_saved = false;
115  // Check simulation end
116  while (true)
117  {
118  // 1. Step: Check end of calculation
119  if (_calculator->CheckEnd(FEXPCOMMON_DEFAULT_VALUE))
120  {
121  if (!result_saved)
122  _calculator->TrySaveResults(FEXPCOMMON_DEFAULT_VALUE, true);
123  break;
124  }
125  // 2. Step: Time increment consistency
126  _calculator->SimulationTimeIncrement (FEXPCOMMON_DEFAULT_VALUE);
127  // 3. Step: Prepare data for new time level
128  _calculator->PrepareDataForNewTimeLevel (FEXPCOMMON_DEFAULT_VALUE);
129  // 4. Step: Update mapping of fe nodes for contact searching
130  _calculator->UpdateModelMapping (FEXPCOMMON_DEFAULT_VALUE);
131  // 5. Step: Transform position and velocities to local coordinate system
132  _calculator->GlobalToLocalTransformation (FEXPCOMMON_DEFAULT_VALUE);
133  // 6. Step: Integration of internal, external and contact forces
134  _calculator->CalculateForces (FEXPCOMMON_DEFAULT_VALUE);
135  // 7. Step: Calculate new displacemnets based on explicit integr. of EOM
136  _calculator->CalculateNewGeometry (FEXPCOMMON_DEFAULT_VALUE);
137  // 8. Step: Save calculation results
138  result_saved = _calculator->TrySaveResults(FEXPCOMMON_DEFAULT_VALUE);
139  // 9. Step: Print out results
140  _calculator->PrintOutResults (FEXPCOMMON_DEFAULT_VALUE);
141  // clear all results --> data space optimization
142  _calculator->ClearResults (FEXPCOMMON_DEFAULT_VALUE);
143  // 10. Step: Control of numerical stability
144  _calculator->StabilityControl (FEXPCOMMON_DEFAULT_VALUE);
145  // 11. Step: Update time step dt
146  _calculator->SetNewTimeStep(_calculator->GetCalculatedCriticTimeStep());
147  }
148  }
149  catch (const std::exception & ex)
150  {
152  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "Error: Computation ended before the simulation end.");
153  // print out the problem of exception
154  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "An exception occurred:");
155  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "--> " + ex.what());
156  }
157 }
158 
165 #define START_THREAD_ID 1
166 
169 {
170 public:
171  ICFEXPThreadDataBase(size_t threads);
172  virtual ~ICFEXPThreadDataBase() { }
173 
174  t_fexpcommon_ct GetTimeStep(size_t thread_id) { return _dt_map[thread_id]; }
175  void SetTimeStep(size_t thread_id, t_fexpcommon_ct value) { _dt_map[thread_id] = value; }
177  void SetMinTStep(t_fexpcommon_ct value);
178 
179  bool GetIsEnd(size_t thread_id) { return _is_end_map[thread_id]; }
180  void SetIsEnd(size_t thread_id, bool value) { _is_end_map[thread_id] = value; }
181  bool CheckEnd();
182  void SetCalcTimeIncrement(size_t thread_id, size_t value) { _time_consistncy_map[thread_id] = value; }
184 
186 protected:
187  std::map<size_t, t_fexpcommon_ct> _dt_map;
188  std::map<size_t, bool> _is_end_map;
189  std::map<size_t, size_t> _time_consistncy_map;
190 private:
191  size_t _threads_number;
192 };
193 
200 
203  : public ICFEXPThreadDataBase
204 {
205 public:
206  CFEXPSolverThreadInputData(size_t threads) : ICFEXPThreadDataBase(threads) { }
208 protected:
209  // [no protected members] -----------------------------
210 private:
211  // [no private members ] -----------------------------
212 };
213 
220 // Cpp thread implementation class for calculation
221 #define PARRALEL_SOLVER_THREAD_TEMPLATE_DEF(cls_thread, cls_data) cls_thread<void(size_t, Ptr<cls_data>), size_t, Ptr<cls_data>>
222 // Simple parallel solver for a single machine
223 #define SIMPLE_PARALLEL_SOLVER CFEXPParallelSolver<CFEXPCalculation, CFEXPSolverThreadInputData, PARRALEL_SOLVER_THREAD_TEMPLATE_DEF(CFEXPCppThread, CFEXPSolverThreadInputData), CFEXPThreadGeneralBarrier>
224 // primary template
225 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier, typename Enable = void>
229 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
231  // specialization
232  <TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
233  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
234  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
235  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
236  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
237  : public ICFEXPSolverBase
238 {
239 public:
241 
242  // override base virtual functions
243  virtual void Start() override;
244  virtual void End () override { FEXPCOMMON_NOT_IMPLEMENTED_EX; }
245  // adding and removing model
246  virtual void AddModel(const t_ModelData & data) override { FEXPCOMMON_NOT_IMPLEMENTED_EX; }
247  virtual void RmvModel(const std::string & key) override { FEXPCOMMON_NOT_IMPLEMENTED_EX; }
248  // current time step dt
251  // serialized data
254 protected:
255  // barrier synchronization
256  enum ESynchronization { eSync1, eSync2, eSync3, eSync4, eSync5, eSync6, eSync7, eSync8, eSync9, eSync10, eSync11, eSyncCount };
257  void Synchronize(ESynchronization barrier);
258 
259  // protected constructor for hybrid solver
260  using t_ThrdInstGetter = std::function<Ptr<TThread>(size_t, Ptr<TThreadData>, bool)>;
262  size_t no_calc_threads, ESynchronization last_barrier, t_ThrdInstGetter thrd_inst_gttr);
263  // creates instance of thread
264  Ptr<TThread> get_thread_instance(size_t id, Ptr<TThreadData> data, bool is_calc_thread);
265  // main calculation function
266  void thread_Calculation_function(size_t thread_id, Ptr<TThreadData> data);
267 
268  size_t _threads;
270  std::map<size_t, Ptr<TThread>> _thread_map;
271  std::map<size_t, Ptr<TExpCalc>> _calculator_map;
272  inline Ptr<TExpCalc> get_calculator(size_t thread_id);
273 
274  // update structe mapping for contact algorithm
275  void update_model_mapping (size_t thread_id);
276  // update time step
277  void update_time_step (Ptr<TThreadData> data);
278  // check of time synchronization correctness
279  void check_time_synchronization (Ptr<TThreadData> data);
280  // save current calculation results
281  std::atomic_bool _result_saved;
282  void try_export_calculation_results(Ptr<TThreadData> data, size_t thread_id);
283  // calculation end checking action
284  bool check_calculation_end(Ptr<TThreadData> data, size_t thread_id);
285 private:
286  // update structe mapping for contact algorithm --> synchronization objects
287  std::mutex _mtx_stuct_map_update;
288  volatile size_t _thread_counter_stuct_map_update;
289  // update time step --> synchronization objects
290  std::mutex _mtx_dt_update;
291  volatile size_t _thread_counter_dt_update;
292  // check of time synchronization correctness --> synchronization objects
293  std::mutex _mtx_time_synchr;
294  volatile size_t _thread_counter_time_synchr;
295  // export calculation results --> synchronization objects
296  std::mutex _mtx_save_res_synchr;
297  volatile size_t _thread_counter_save_res_synchr;
298  // check of calculation end --> synchronization objects
299  std::mutex _mtx_calc_end_synchr;
300  volatile size_t _thread_counter_calc_end_synchr;
301  // initialize
302  void initialize(size_t threads, size_t no_calc_threads, ESynchronization last_barrier, t_ThrdInstGetter thrd_inst_gttr);
303  // synchronization barriers
304  Ptr<Tbarrier> _barrier[ESynchronization::eSyncCount];
305 };
306 
307 // member functions
309 //--------------------------------------------------------------------------------------
310 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
311 CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
312  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
313  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
314  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
315  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
317  : ICFEXPSolverBase(builder, exporter), _result_saved(false)
318 //--------------------------------------------------------------------------------------
319 {
321  _builder->GetModelContainer()->GetModelElement(ICFEXPSetting::ESettingType::eModelBase, ESystemElementType::eSetting))->GetThreadNumber();
322  // initialize solver
323  initialize(threads, FEXPCOMMON_DEFAULT_VALUE, ESynchronization::eSync9, [this](auto val1, auto val2, auto val3) { return get_thread_instance(val1, val2, val3); });
324 }
325 
326 //--------------------------------------------------------------------------------------
327 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
328 CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
329  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
330  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
331  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
332  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
334  size_t no_calc_threads, ESynchronization last_barrier, t_ThrdInstGetter thrd_inst_gttr)
335  : ICFEXPSolverBase(builder, exporter), _result_saved(false)
336 //--------------------------------------------------------------------------------------
337 {
338 #define PARALLEL_SOLVER_ERROR_THREADS "Error: Try exclude too much threads \""
340  _builder->GetModelContainer()->GetModelElement(ICFEXPSetting::ESettingType::eModelBase, ESystemElementType::eSetting));
341  auto threads_setting_num = setting->GetThreadNumber();
342  if (threads_setting_num <= no_calc_threads)
343  {
344  std::string error = PARALLEL_SOLVER_ERROR_THREADS + CFEXPBaseConvers::NumberToString<size_t>(no_calc_threads) + "\"!!!\n";
345  error += "--> Allowable number of threads is \"" + CFEXPBaseConvers::NumberToString<size_t>(threads_setting_num) + "\".";
346  FEXPCOMMON_EXCEPTION(error);
347  }
348  // set new number of calculation threads
349  setting->SetThreadNumber(threads_setting_num - no_calc_threads);
350  // update model mapping to threads
351  _builder->ScheduleThreads(ESystemElementType::eNode);
352  _builder->ScheduleThreads(ESystemElementType::eElement);
353  // initialize solver
354  initialize(setting->GetThreadNumber(), no_calc_threads, last_barrier, thrd_inst_gttr);
355 }
356 
357 //--------------------------------------------------------------------------------------
358 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
359 void CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
360  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
361  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
362  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
363  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
364  ::initialize(size_t threads, size_t no_calc_threads, ESynchronization last_barrier, t_ThrdInstGetter thrd_inst_gttr)
365 //--------------------------------------------------------------------------------------
366 {
367  _threads = threads;
368  _thread_counter_stuct_map_update = FEXPCOMMON_DEFAULT_VALUE;
369  _thread_counter_dt_update = FEXPCOMMON_DEFAULT_VALUE;
370  _thread_counter_time_synchr = FEXPCOMMON_DEFAULT_VALUE;
371  _thread_counter_save_res_synchr = FEXPCOMMON_DEFAULT_VALUE;
372  _thread_counter_calc_end_synchr = FEXPCOMMON_DEFAULT_VALUE;
373  _thread_data = CFEXPDataManager<TThreadData>::SafeAllocInstance(_threads);
374  // calculation threads
375  auto thread_id = *_thread_data->GetThreadId().get(); auto calc_thread_num = thread_id.size();
376  FEXPCOMMON_FOREACH_ITER_FNC(thread_id,
377  {
378  // thread ID
379  auto id = IT;
380  // create thread instances
381  _thread_map.insert(MAP_PAIR(id, thrd_inst_gttr(id, _thread_data, true)));
382  // create calculation instance
383  _calculator_map.insert(MAP_PAIR(id, CFEXPDataManager<TExpCalc>::SafeAllocInstance(_builder->GetModelContainer(), _exporter,
384  [this] { update_topology_map_for_contact(); }, [this](auto in1, auto in2) { return check_node(in1, in2); })));
385  });
386  // no calculation threads --> other purpose
387  auto thread_data_no_calc = *CFEXPDataManager<TThreadData>::SafeAllocInstance(no_calc_threads)->GetThreadId().get();
388  FEXPCOMMON_FOREACH_ITER_FNC(thread_data_no_calc,
389  {
390  auto thread_id_gen = size_t(FEXPCOMMON_DEFAULT_VALUE);
391  while (true)
392  {
393  if (_thread_map.count(++thread_id_gen))
394  continue;
395  _thread_map.insert(MAP_PAIR(thread_id_gen, thrd_inst_gttr(thread_id_gen, _thread_data, false)));
396  break;
397  }
398  });
399  // create thread barriers
400  size_t idx;
401  FEXPCOMMON_FOREACH(size_t(ESynchronization::eSync1), size_t(last_barrier), idx)
402  _barrier[idx] = CFEXPDataManager<Tbarrier>::SafeAllocInstance(thread_id.size() + thread_data_no_calc.size());
403 }
404 
405 //--------------------------------------------------------------------------------------
406 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
407 void CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
408  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
409  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
410  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
411  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
412  ::Start()
413 //--------------------------------------------------------------------------------------
414 {
415  FEXPCOMMON_FOREACH_ITER_FNC(_thread_map, { _thread_map[IT.first]->StartThread(); });
416  FEXPCOMMON_FOREACH_ITER_FNC(_thread_map, { _thread_map[IT.first]->Join (); });
417 }
418 
419 //--------------------------------------------------------------------------------------
420 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
421 Ptr<TThread> CFEXPParallelSolver<TExpCalc , TThreadData, TThread, Tbarrier, typename std::enable_if<
422  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
423  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
424  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
425  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
426  ::get_thread_instance(size_t id, Ptr<TThreadData> data, bool is_calc_thread)
427 //--------------------------------------------------------------------------------------
428 {
430  [this](auto it1, auto it2) { CFEXPParallelSolver::thread_Calculation_function(it1, it2); }, id, data);
431 }
432 
433 //--------------------------------------------------------------------------------------
434 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
435 void CFEXPParallelSolver<TExpCalc , TThreadData, TThread, Tbarrier, typename std::enable_if<
436  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
437  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
438  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
439  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
440  ::thread_Calculation_function(size_t thread_id, Ptr<TThreadData> data)
441 //--------------------------------------------------------------------------------------
442 {
443  try
444  {
445  bool calculation_end = false; auto calculator = get_calculator(thread_id);
446  while (true)
447  {
448  // 1. Step: Set time consistency
449  data->SetCalcTimeIncrement(thread_id, calculator->SimulationTimeIncrement(thread_id));
450  Synchronize(ESynchronization::eSync1);
451  // 2. Step: Check if time is the same for all threads
452  // this require only one thread to do this action
453  check_time_synchronization(data);
454  // check end of calculation --> wait for thread saving results
455  calculation_end = check_calculation_end(data, thread_id);
456  Synchronize(ESynchronization::eSync2);
457  // 3. Step: Check end of computation
458  if (calculation_end)
459  break;
460  Synchronize(ESynchronization::eSync3);
461  // 4. Step: Prepare data for new time level
462  calculator->PrepareDataForNewTimeLevel(thread_id);
463  // 5. Step: Update mapping of fe nodes for contact search
464  // this require only one thread to do this action
465  update_model_mapping(thread_id);
466  // 6. Step: Transform position and velocities to local coordinate system
467  calculator->GlobalToLocalTransformation(thread_id);
468  Synchronize(ESynchronization::eSync4);
469  // 7. Step: Integration of internal, external and contact forces
470  calculator->CalculateForces(thread_id);
471  Synchronize(ESynchronization::eSync5);
472  // 8. Step: Compute new displacements based on explicit integration of EM
473  calculator->CalculateNewGeometry(thread_id);
474  Synchronize(ESynchronization::eSync6);
475  // 9.1. Step: Export results
476  try_export_calculation_results(data, thread_id);
477  // 9.2. Step: Print out results
478  calculator->PrintOutResults(thread_id);
479  Synchronize(ESynchronization::eSync7);
480  // 10. Step: Control of numerical stability
481  calculator->StabilityControl(thread_id);
482  data->SetTimeStep(thread_id, calculator->GetCalculatedCriticTimeStep());
483  Synchronize(ESynchronization::eSync8);
484  // 11. Step: Update time step dt
485  // this require only one thread to do this action
486  update_time_step(data);
487  // 12. Step: Synchronize befor new loop
488  Synchronize(ESynchronization::eSync9);
489  }
490  }
491  catch (const std::exception & ex)
492  {
494  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "Error: Calculation ended before simulation end.");
495  // print problem of exception
496  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "An exception occurred:");
497  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "--> " + ex.what());
498  }
499 }
500 
501 //--------------------------------------------------------------------------------------
502 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
503 Ptr<TExpCalc> CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
504  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
505  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
506  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
507  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
508  ::get_calculator(size_t thread_id)
509 //--------------------------------------------------------------------------------------
510 {
511  return _calculator_map[thread_id];
512 }
513 
514 // value of thread counter of in critical section to update
515 #define THREAD_COUNT_UPDATER 1
516 //--------------------------------------------------------------------------------------
517 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
518 void CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
519  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
520  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
521  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
522  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
523  ::update_model_mapping(size_t thread_id)
524 //--------------------------------------------------------------------------------------
525 {
526  // critical section for model mapping update
527  std::unique_lock<std::mutex> lock(_mtx_stuct_map_update, std::defer_lock);
528  lock.lock();
529  ++_thread_counter_stuct_map_update; // increment thread counter
530  if (_thread_counter_stuct_map_update == THREAD_COUNT_UPDATER)
531  get_calculator(thread_id)->UpdateModelMapping(thread_id);
532  if (_thread_counter_stuct_map_update == _threads)
533  _thread_counter_stuct_map_update = FEXPCOMMON_DEFAULT_VALUE;
534  lock.unlock();
535 }
536 
537 //--------------------------------------------------------------------------------------
538 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
539 void CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
540  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
541  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
542  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
543  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
544  ::update_time_step(Ptr<TThreadData> data)
545 //--------------------------------------------------------------------------------------
546 {
547  // critical section for setting of new time step
548  std::unique_lock<std::mutex> lock(_mtx_dt_update, std::defer_lock);
549  lock.lock();
550  ++_thread_counter_dt_update; // increment thread counter
551  if (_thread_counter_dt_update == THREAD_COUNT_UPDATER)
552  {
553  auto min_dt = data->GetMinTStep();
554  FEXPCOMMON_FOREACH_ITER_FNC(_thread_map,
555  {
556  if (_calculator_map.count(IT.first))
557  _calculator_map[IT.first]->SetNewTimeStep(min_dt);
558  });
559  }
560  if (_thread_counter_dt_update == _threads)
561  _thread_counter_dt_update = FEXPCOMMON_DEFAULT_VALUE;
562  lock.unlock();
563 }
564 
565 //--------------------------------------------------------------------------------------
566 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
567 void CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
568  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
569  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
570  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
571  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
572  ::check_time_synchronization(Ptr<TThreadData> data)
573 //--------------------------------------------------------------------------------------
574 {
575  // critical section for setting of new time step
576  std::unique_lock<std::mutex> lock(_mtx_time_synchr, std::defer_lock);
577  lock.lock();
578  ++_thread_counter_time_synchr; // increment thread counter
579  if (_thread_counter_time_synchr == THREAD_COUNT_UPDATER)
580  // if values for all threads are not the same -- exception is thrown
581  data->CheckCalcTimeConsistency();
582  if (_thread_counter_time_synchr == _threads)
583  _thread_counter_time_synchr = FEXPCOMMON_DEFAULT_VALUE;
584  lock.unlock();
585 }
586 
587 //--------------------------------------------------------------------------------------
588 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
589 void CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
590  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
591  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
592  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
593  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
594  ::try_export_calculation_results(Ptr<TThreadData> data, size_t thread_id)
595 //--------------------------------------------------------------------------------------
596 {
597  // critical section for export of results from numerical simulation
598  std::unique_lock<std::mutex> lock(_mtx_save_res_synchr, std::defer_lock);
599  lock.lock();
600  ++_thread_counter_save_res_synchr; // increment thread counter
601  if (_thread_counter_save_res_synchr == THREAD_COUNT_UPDATER)
602  {
603  auto calculator = get_calculator(thread_id);
604  _result_saved.store(calculator->TrySaveResults(FEXPCOMMON_DEFAULT_VALUE));
605  // clear all results --> data space optimization
606  calculator->ClearResults(FEXPCOMMON_DEFAULT_VALUE);
607  }
608  if (_thread_counter_save_res_synchr == _threads)
609  _thread_counter_save_res_synchr = FEXPCOMMON_DEFAULT_VALUE;
610  lock.unlock();
611 }
612 
613 //--------------------------------------------------------------------------------------
614 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
615 bool CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
616  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
617  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
618  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
619  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
620  ::check_calculation_end(Ptr<TThreadData> data, size_t thread_id)
621 //--------------------------------------------------------------------------------------
622 {
623  auto calculator = get_calculator(thread_id);
624  // check calulation end
625  auto result = calculator->CheckEnd(thread_id);
626  data->SetIsEnd(thread_id, result);
627  // critical section for calculation results export
628  std::unique_lock<std::mutex> lock(_mtx_calc_end_synchr, std::defer_lock);
629  lock.lock();
630  ++_thread_counter_calc_end_synchr; // increment thread counter
631  if (_thread_counter_calc_end_synchr == THREAD_COUNT_UPDATER)
632  {
633  // if is end
634  if (result && !_result_saved.load())
635  {
636  _result_saved.store(calculator->TrySaveResults(FEXPCOMMON_DEFAULT_VALUE, true));
637  // clear all results --> data space optimization
638  calculator->ClearResults(FEXPCOMMON_DEFAULT_VALUE);
639  }
640  }
641  if (_thread_counter_calc_end_synchr == _threads)
642  _thread_counter_calc_end_synchr = FEXPCOMMON_DEFAULT_VALUE;
643  lock.unlock();
644  return result;
645 }
646 
647 //--------------------------------------------------------------------------------------
648 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
649 void CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier, typename std::enable_if<
650  std::is_base_of<ICFEXPExplicitCalcBase , TExpCalc >::value &&
651  std::is_base_of<ICFEXPThreadDataBase , TThreadData>::value &&
652  std::is_base_of<ICFEXPThreadBase , TThread >::value &&
653  std::is_base_of<ICFEXPSynchrThreadBarrier, Tbarrier >::value>::type>
654  ::Synchronize(ESynchronization barrier)
655 //--------------------------------------------------------------------------------------
656 {
657  _barrier[barrier]->SynchronizeThreads();
658 }
659 
666 #define HYBRID_PARALLEL_SOLVER_EXCLUDE_THREADS 1
667 #define HYBRID_PARALLEL_SOLVER CFEXPHybridParallelSolver<CFEXPCalculation, CFEXPSolverThreadInputData, PARRALEL_SOLVER_THREAD_TEMPLATE_DEF(CFEXPCppThread, CFEXPSolverThreadInputData), CFEXPThreadGeneralBarrier>
668 
670 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
672  : public CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier>
673 {
674 public:
675  CFEXPHybridParallelSolver(std::function<Ptr<CFEXPFEInpContBase>(std::string &, Ptr<std::vector<std::string>>)> reader, Ptr<ICFEXPModelBuilderBase> builder,
676  std::function<std::string(size_t)> model_key_gttr, ICFEXPNetClientNodeService & net_service);
677 
678  // override base virtual functions
679  virtual void Start() override;
680 protected:
681  Ptr<TThread> get_thread_instance(size_t id, Ptr<TThreadData> data, bool is_calc_thread);
682  // main calculation function
683  void thread_Calculation_function(size_t thread_id, Ptr<TThreadData> data);
684 private:
685  bool _socket_closed;
686  // reader of model data
687  std::function<Ptr<CFEXPFEInpContBase>(std::string &, Ptr<std::vector<std::string>>)> _data_reader;
688  // communication with server
689  void main_loop_net_communication(size_t id, Ptr<TThreadData> data);
690  // inform about calculation end
691  bool end_calculation (Ptr<TThreadData> data);
692  // result export
693  void result_export (Ptr<TThreadData> data, bool forced = false);
694  void try_result_export_rntm (Ptr<TThreadData> data, bool forced = false);
695  void try_result_export_full (Ptr<TThreadData> data, bool forced = false);
696  // stabil time step synchronization
697  void time_step_synchronization (Ptr<TThreadData> data);
698  // model contact --> data exchange
699  // send bounding box data
700  void macro_model_BB_data_send (Ptr<TThreadData> data);
701  // send macro model serialized runtime calculation data
702  void macro_model_calc_data_send (Ptr<TThreadData> data);
703  // receive macro model input data
704  void macro_model_input_data_recv(Ptr<TThreadData> data);
705  // receive macro model serialized runtime calculation data
706  void macro_model_calc_data_recv (Ptr<TThreadData> data);
707  // checking socket error
708  bool is_socket_closed(Ptr<std::map<size_t, Ptr<t_ModelData>>> data);
709  std::function<std::string(size_t)> _model_key_gttr;
710  ICFEXPNetClientNodeService & _net_calc_service;
711 };
712 
713 // member functions
715 //--------------------------------------------------------------------------------------
716 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
719  std::function<Ptr<CFEXPFEInpContBase>(std::string &, Ptr<std::vector<std::string>>)> reader, Ptr<ICFEXPModelBuilderBase> builder,
720  std::function<std::string(size_t)> model_key_gttr, ICFEXPNetClientNodeService & net_service)
721  : CFEXPParallelSolver<TExpCalc, TThreadData, TThread, Tbarrier>(builder, Ptr<ICFEXPResultExport>(), HYBRID_PARALLEL_SOLVER_EXCLUDE_THREADS, ESynchronization::eSync11,
722  [this](auto val1, auto val2, auto val3) { return get_thread_instance(val1, val2, val3); }), _model_key_gttr(model_key_gttr),
723  _net_calc_service(net_service), _socket_closed(false), _data_reader(reader) { }
724 //--------------------------------------------------------------------------------------
725 
726 //--------------------------------------------------------------------------------------
727 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
730 //--------------------------------------------------------------------------------------
731 {
732  CFEXPParallelSolver::Start();
733 }
734 
735 //--------------------------------------------------------------------------------------
736 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
738  ::get_thread_instance(size_t id, Ptr<TThreadData> data, bool is_calc_thread)
739 //--------------------------------------------------------------------------------------
740 {
741  return is_calc_thread ?
742  CFEXPDataManager<TThread>::SafeAllocInstance(// create calculation thread
743  [this](auto it1, auto it2) { CFEXPHybridParallelSolver::thread_Calculation_function(it1, it2); }, id, data) :
744  CFEXPDataManager<TThread>::SafeAllocInstance(// create thread for network communication purpose
745  [this](auto it1, auto it2) { CFEXPHybridParallelSolver::main_loop_net_communication(it1, it2); }, id, data);
746 }
747 
748 //--------------------------------------------------------------------------------------
749 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
752 //--------------------------------------------------------------------------------------
753 {
754  try
755  {
756  bool calculation_end = false; auto calculator = get_calculator(thread_id);
757  while (!_socket_closed)
758  {
759  // 1. Step: Set time consistency
760  data->SetCalcTimeIncrement(thread_id, calculator->SimulationTimeIncrement(thread_id));
761  Synchronize(ESynchronization::eSync1);
762  // 2. Step: Check if time is the same for all threads
763  // this require only one thread to do this action
764  check_time_synchronization(data);
765  // check end of calculation
766  calculation_end = check_calculation_end(data, thread_id);
767  Synchronize(ESynchronization::eSync2);
768  // 3. Step: While is end wait for result sending --> process non-calc thread communicates with server
769  Synchronize(ESynchronization::eSync3);
770  // 4. Step: Check end of calculation
771  if (calculation_end)
772  break;
773  Synchronize(ESynchronization::eSync4);
774  // 5. Step: Prepare data for new time level
775  calculator->PrepareDataForNewTimeLevel(thread_id);
776  // 6. Step: Update mapping of fe nodes for contact search
777  // this require only one thread to do this action
778  update_model_mapping(thread_id);
779  // 7. Step: Transform position and velocities to local coordinate system
780  calculator->GlobalToLocalTransformation(thread_id);
781  Synchronize(ESynchronization::eSync5);
782  // 8. Step: Integration of internal, external and contact forces
783  calculator->CalculateForces(thread_id);
784  Synchronize(ESynchronization::eSync6);
785  // 9. Step: Calculate new motion based on explicit integration equations of motion
786  calculator->CalculateNewGeometry(thread_id);
787  Synchronize(ESynchronization::eSync7);
788  // 10. Step: Save calculation results --> process non-calc thread communicates with server
789  Synchronize(ESynchronization::eSync8);
790  // 11. Step: Control of calculation stability
791  calculator->StabilityControl(thread_id);
792  data->SetTimeStep(thread_id, calculator->GetCalculatedCriticTimeStep());
793  Synchronize(ESynchronization::eSync9);
794  // 13. Step: Synchronize time steps with network clients --> process non-calc thread communicates with server
795  Synchronize(ESynchronization::eSync10);
796  // 15. Step: Network data exchange --> process non-calc thread communicates with server
797  Synchronize(ESynchronization::eSync11);
798  }
799  }
800  catch (const std::exception & ex)
801  {
803  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "Error: Calculation ended before simulation end.");
804  // print problem of exception
805  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "An exception occurred:");
806  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "--> " + ex.what());
807  }
808 }
809 
810 //--------------------------------------------------------------------------------------
811 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
814 //--------------------------------------------------------------------------------------
815 {
816  try
817  {
818  bool calculation_end = false;
819  while (!_socket_closed)
820  {
821  Synchronize(ESynchronization::eSync1 );
822  Synchronize(ESynchronization::eSync2 );
823  // check calculation end --> send resuts
824  calculation_end = end_calculation(data);
825  Synchronize(ESynchronization::eSync3 );
826  // check calculation end --> end of loop
827  if (calculation_end)
828  break;
829  Synchronize(ESynchronization::eSync4 );
830  Synchronize(ESynchronization::eSync5 );
831  Synchronize(ESynchronization::eSync6 );
832  Synchronize(ESynchronization::eSync7 );
833  // export of results
834  result_export (data);
835  Synchronize(ESynchronization::eSync8 );
836  Synchronize(ESynchronization::eSync9 );
837  // stability --> time step synchonization
838  time_step_synchronization (data);
839  Synchronize(ESynchronization::eSync10);
840  // macro contact --> data exchange
841  // 1. send macro model bounding boxes
842  macro_model_BB_data_send (data);
843  // 2. send macro model serialized calculation data
844  macro_model_calc_data_send (data);
845  // 3. receive macro model input data
846  macro_model_input_data_recv(data);
847  // 4. receive macro model serialized calculation data
848  macro_model_calc_data_recv (data);
849  Synchronize(ESynchronization::eSync11);
850  }
851  }
852  catch (const std::exception & ex)
853  {
855  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "Error: Calculation ended before simulation end.");
856  // print problem of exception
857  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "An exception occurred:");
858  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "--> " + ex.what());
859  }
860 }
861 
862 //--------------------------------------------------------------------------------------
863 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
866 //--------------------------------------------------------------------------------------
867 {
868  // check end of calculation
869  auto is_end = data->CheckEnd();
870 
871  // 1. receive message request for getting results
872  auto instruction = _net_calc_service.ReadInstruction();
873  if (is_socket_closed(instruction))
874  return is_end;
875  if (!instruction->count(t_ENetMessage::eGetIsEndCalc))
876  FEXPCOMMON_EXCEPTION("Error: 1. End of calculation check --> Wrong message!!!");
877 
878  // 2. send info
879  auto cekey = std::string("ce");
881  cedta->insert(MAP_PAIR(cekey, CFEXPDataManager<std::vector<std::string>>::SafeAllocInstance()));
882  _net_calc_service.SendInstruction(!is_end ? t_ENetMessage::eContinue : t_ENetMessage::eSetIsEndCalc, cedta);
883  if (is_end)
884  result_export(data, true); // send calculation results of final time step
885  return is_end;
886 }
887 
888 //--------------------------------------------------------------------------------------
889 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
891  ::result_export(Ptr<TThreadData> data, bool forced/*= false*/)
892 //--------------------------------------------------------------------------------------
893 {
894 
895  // try export runtime calc data
896  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "Info: Try export runtime results.");
897  try_result_export_rntm(data, forced);
898  // try export full results
899  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "Info: Try export results." );
900  try_result_export_full(data, forced);
901  CFEXPLog::WriteLine(FEXPCOMMON_DFLT_TXT + "Info: Export of results finished.");
902 }
903 
904 //--------------------------------------------------------------------------------------
905 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
907  ::try_result_export_rntm(Ptr<TThreadData> data, bool forced/*= false*/)
908 //--------------------------------------------------------------------------------------
909 {
910  // receive message request for getting results from runtime calculation data
911  auto instruction = _net_calc_service.ReadInstruction();
912  if (is_socket_closed(instruction))
913  return;
914  if (!instruction->count(t_ENetMessage::eGetResults))
915  FEXPCOMMON_EXCEPTION("Error: Export of results (runtime output) --> Wrong message!!!");
916 
917  // save calc. data to print out
918  auto rsokey = std::string("rso");
919  auto output = std::string(FEXPCOMMON_EMPTY_STRING);
920  FEXPCOMMON_FOREACH_ITER(_calculator_map)
921  {
922  auto nid = CFEXPBaseConvers::StringToNumber<size_t>(instruction->at(t_ENetMessage::eGetResults)->at(rsokey)->at(0));
923  auto dof = CFEXPBaseConvers::StringToNumber<size_t>(instruction->at(t_ENetMessage::eGetResults)->at(rsokey)->at(1));
925  _builder->GetModelContainer()->GetModelElement(nid, ESystemElementType::eNode, IT->first)), dof);
926  if (output != FEXPCOMMON_EMPTY_STRING)
927  break;
928  }
930  rsodta->insert(MAP_PAIR(rsokey, CFEXPDataManager<std::vector<std::string>>::SafeAllocInstance()));
931  rsodta->at(rsokey)->push_back(output);
932  _net_calc_service.SendInstruction(t_ENetMessage::eSetResults, rsodta);
933 }
934 
935 //--------------------------------------------------------------------------------------
936 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
938  ::try_result_export_full(Ptr<TThreadData> data, bool forced/*= false*/)
939 //--------------------------------------------------------------------------------------
940 {
941  // receive message request for getting results
942  auto instruction = _net_calc_service.ReadInstruction();
943  if (is_socket_closed(instruction))
944  return;
945  if (!instruction->count(t_ENetMessage::eGetResults))
946  FEXPCOMMON_EXCEPTION("Error: Export of results --> Wrong message!!!");
947 
948  auto calculator = get_calculator(_calculator_map.size());
949  // send results if need
950  auto rskey = std::string("rs");
952  rsdta->insert(MAP_PAIR(rskey, CFEXPDataManager<std::vector<std::string>>::SafeAllocInstance()));
953  if (!calculator->TrySaveResults(FEXPCOMMON_DEFAULT_VALUE, forced))
954  {
955  _net_calc_service.SendInstruction(t_ENetMessage::eSetResults, rsdta);
956  return;
957  }
958 
959  // get current result saved in container
961  _builder->GetModelContainer()->IterateModElems([this, &result](auto item)
962  {
963  if (result)
964  FEXPCOMMON_EXCEPTION("Error: Export of results --> More results remains in container!!!");
966  return true;
968  if (!result)
969  {
970  _net_calc_service.SendInstruction(t_ENetMessage::eSetResults, rsdta);
971  return;
972  }
973 
974  // create result map to send (serizalization)
978  // block definition
979  rsdta->at(rskey)->push_back(std::string(FEXPCOMMON_KEY_BLOCK_IDNTF) + RESULT_FILE_STRUCT_BLCS[block]);
980  // node results table definition
982  rsdta->at(rskey)->push_back(table_def_nd);
983  // serialize node result data
984  FEXPCOMMON_FOREACH_ITER_FNC(result->GetNodeResults(), { rsdta->at(rskey)->push_back(IT->GetSerializedData()); });
985 
986  // finite element connectivity results table definition
988  rsdta->at(rskey)->push_back(table_def_fe);
989  // serialize connectivity data
990  // serialize node result data
991  FEXPCOMMON_FOREACH_ITER_FNC(result->GetConnectivity(), { rsdta->at(rskey)->push_back(IT->GetSerializedData()); });
992 
993  // send serialized result data data
994  _net_calc_service.SendInstruction(t_ENetMessage::eSetResults, rsdta);
995  // clear all results --> data space optimization
996  calculator->ClearResults(FEXPCOMMON_DEFAULT_VALUE);
997 }
998 
999 //--------------------------------------------------------------------------------------
1000 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
1003 //--------------------------------------------------------------------------------------
1004 {
1005  // 1. receive message request for new time step
1006  auto instruction = _net_calc_service.ReadInstruction();
1007  if (is_socket_closed(instruction))
1008  return;
1009  if (!instruction->count(t_ENetMessage::eGetStabilDt))
1010  FEXPCOMMON_EXCEPTION("Error: 1. Time step --> Wrong message!!!");
1011 
1012  // 2. send time step and synchronize with network clients
1013  auto dtkey = std::string("dt");
1014  auto mindt = data->GetMinTStep();
1016  tdata->insert(MAP_PAIR(dtkey, CFEXPDataManager<std::vector<std::string>>::SafeAllocInstance()));
1017  tdata->at(dtkey)->push_back(CFEXPBaseConvers::NumberToString<t_fexpcommon_ct>(mindt));
1018  _net_calc_service.SendInstruction(t_ENetMessage::eSetStabilDt, tdata);
1019 
1020  // 3. update time step after sending current one
1021  instruction = _net_calc_service.ReadInstruction();
1022  if (is_socket_closed(instruction))
1023  return;
1024  if (!instruction->count(t_ENetMessage::eSetStabilDt))
1025  FEXPCOMMON_EXCEPTION("Error: 2. Time step --> Wrong message!!!");
1026  // set time step for each calculation thread
1027  data->SetMinTStep(CFEXPBaseConvers::StringToNumber<t_fexpcommon_ct>(
1028  ICFEXPNetClientNodeService::GetReadModelData(instruction, t_ENetMessage::eSetStabilDt)[dtkey]->at(FEXPCOMMON_DEFAULT_INDX)));
1029  // update time step
1030  update_time_step(data);
1031 }
1032 
1033 //--------------------------------------------------------------------------------------
1034 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
1037 //--------------------------------------------------------------------------------------
1038 {
1039  // 1. compose bounding boxes
1040  //--> get bounding boxes for each macro model based on its unique ID
1041  auto bbox = std::map<size_t, Ptr<CFEXGeomTools::t_BoundBox>>();
1042  _builder->GetModelContainer()->IterateModElems([this, &bbox](auto item)
1043  {
1044  auto id = item->GetModelId();
1045  if (!bbox.count(id))
1046  bbox.insert(MAP_PAIR(id, Ptr<CFEXGeomTools::t_BoundBox>()));
1047  bbox[id] = CFEXGeomTools::GetBoundingBox(bbox[id],
1049  return true;
1052 
1053  // 2. send bounding box of all models
1054  auto bbidkey = std::string("bbid"); // bounding box id key
1055  auto bbdtkey = std::string("bbdt"); // bounding box data key
1057  {
1058  // 2.1 receive message request for sending bounding box ID
1059  auto instructionid = _net_calc_service.ReadInstruction();
1060  if (is_socket_closed(instructionid))
1061  return;
1062  if (!instructionid->count(t_ENetMessage::eGetBoundBoxId))
1063  FEXPCOMMON_EXCEPTION("Error: Bounding box --> Wrong message!!!");
1064 
1065  // 2.2 send bounding box ID
1067  bbiddata->insert(MAP_PAIR(bbidkey, CFEXPDataManager<std::vector<std::string>>::SafeAllocInstance()));
1068  bbiddata->at(bbidkey)->push_back(CFEXPBaseConvers::NumberToString((*IT).first));
1069  _net_calc_service.SendInstruction(t_ENetMessage::eSetBoundBoxId, bbiddata);
1070 
1071  // 2.3 receive message request for sending bounding box
1072  auto instructiondt = _net_calc_service.ReadInstruction();
1073  if (is_socket_closed(instructiondt))
1074  return;
1075  if (!instructiondt->count(t_ENetMessage::eGetBoundBox))
1076  FEXPCOMMON_EXCEPTION("Error: Bounding box --> Wrong message!!!");
1077 
1078  // 2.4 send bounding box
1080  bbdtdata->insert(MAP_PAIR(bbdtkey, CFEXPDataManager<std::vector<std::string>>::SafeAllocInstance()));
1081  auto serialbb = CFEXGeomTools::GetSerializedBoundingBox((*IT).second);
1082  FEXPCOMMON_FOREACH_ITER_FNC(*serialbb.get(), { bbdtdata->at(bbdtkey)->push_back(IT); });
1083  _net_calc_service.SendInstruction(t_ENetMessage::eSetBoundBox, bbdtdata);
1084  }
1085 
1086  // end of data sending
1087  // receive message request for sending bounding box ID
1088  auto instructionid = _net_calc_service.ReadInstruction();
1089  if (is_socket_closed(instructionid))
1090  return;
1091  if (!instructionid->count(t_ENetMessage::eGetBoundBoxId))
1092  FEXPCOMMON_EXCEPTION("Error: Bounding box --> Wrong message!!!");
1093  // send empty bounding box ID to end this session
1095  bbiddata->insert(MAP_PAIR(bbidkey, CFEXPDataManager<t_ModelDataDta>::SafeAllocInstance()));
1096  _net_calc_service.SendInstruction(t_ENetMessage::eSetBoundBoxId, bbiddata);
1097 }
1098 
1099 //--------------------------------------------------------------------------------------
1100 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
1103 //--------------------------------------------------------------------------------------
1104 {
1105  // 1. get request about getting of macro model serialized calculation data and send them to server
1106  auto trkeyget = "trget"; // get transfer data key
1107  auto trkeyset = "trset"; // set transfer data key
1108  auto reschedule = false;
1109  while (true)
1110  {
1111  // 1.1 receive message request for sending respective macro model calc. data
1112  auto instruction = _net_calc_service.ReadInstruction();
1113  if (is_socket_closed(instruction))
1114  break;
1115  if (!instruction->count(t_ENetMessage::eGetMacroModelCalcData))
1116  FEXPCOMMON_EXCEPTION("Error: Macro model calculation data --> Wrong message!!!");
1117  // macro model data ID
1118  auto requestdata = ICFEXPNetClientNodeService::GetReadModelData(instruction, t_ENetMessage::eGetMacroModelCalcData);
1119  if (requestdata[trkeyget]->empty())
1120  {
1121  _net_calc_service.SendInstruction(t_ENetMessage::eSetMacroModelCalcData, CFEXPDataManager<t_ModelData>::SafeAllocInstance());
1122  break;
1123  }
1124 
1125  // 1.2 Send macro model calc. data
1126  auto macro_id_str = requestdata[trkeyget]->at(FEXPCOMMON_DEFAULT_INDX);
1127  // compose serialized calculation data -- NODES
1128  auto macro = _builder->NetSerializeStructure(macro_id_str);
1129  if (!macro || macro->empty())
1130  FEXPCOMMON_EXCEPTION("Error: Macro model input data ID --> No such data!!!");
1131  auto macrocalcdata = CFEXPDataManager<t_ModelData>::SafeAllocInstance();
1132  macrocalcdata->insert(MAP_PAIR(trkeyset, macro));
1133  _net_calc_service.SendInstruction(t_ENetMessage::eSetMacroModelCalcData, macrocalcdata);
1134  // removing of entire model
1135  _builder->RemoveStructure(macro_id_str);
1136  reschedule = true;
1137  }
1138  // reschedule model if need
1139  if (!reschedule)
1140  return;
1141  _builder->ScheduleThreads(ESystemElementType::eNode );
1142  _builder->ScheduleThreads(ESystemElementType::eElement);
1143 }
1144 
1145 //--------------------------------------------------------------------------------------
1146 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
1149 //--------------------------------------------------------------------------------------
1150 {
1151  // 1. get request about sending of macro model input data
1152  auto trkeyset = "trset"; // set transfer data key
1153  auto macro_in_data = CFEXPDataManager<t_ModelData>::SafeAllocInstance();
1154  while (true)
1155  {
1156  // 1.1 receive message request for sending respective macro model input data ID
1157  auto instruction1 = _net_calc_service.ReadInstruction();
1158  if (is_socket_closed(instruction1))
1159  break;
1160  if (!instruction1->count(t_ENetMessage::eSetMacroModelId))
1161  FEXPCOMMON_EXCEPTION("Error: Macro model input (set) data ID --> Wrong message!!!");
1162  // macro model input data ID
1163  auto requestdata1 = ICFEXPNetClientNodeService::GetReadModelData(instruction1, t_ENetMessage::eSetMacroModelId);
1164  if (requestdata1[trkeyset]->empty())
1165  break;
1166  auto model_id = requestdata1[trkeyset]->at(FEXPCOMMON_DEFAULT_INDX);
1167 
1168  // 1.2 read macro model input data
1169  auto instruction2 = _net_calc_service.ReadInstruction();
1170  if (is_socket_closed(instruction2))
1171  break;
1172  if (!instruction2->count(t_ENetMessage::eSetMacroModel))
1173  FEXPCOMMON_EXCEPTION("Error: Macro model input (set) data --> Wrong message!!!");
1174  // macro model data
1175  auto requestdata2 = ICFEXPNetClientNodeService::GetReadModelData(instruction2, t_ENetMessage::eSetMacroModel);
1176  if (requestdata2[trkeyset]->empty())
1177  break;
1178  macro_in_data->insert(MAP_PAIR(model_id, CFEXPDataManager<t_ModelDataDta>::SafeAllocInstance()));
1179  FEXPCOMMON_FOREACH_ITER_FNC(*requestdata2[trkeyset].get(), { macro_in_data->at(model_id)->push_back(IT); });
1180  }
1181  // create models
1182  if (macro_in_data->empty())
1183  return;
1184  // build new models
1185  FEXPCOMMON_FOREACH_ITER_FNC(*macro_in_data.get(),
1186  {
1187  auto key = IT.first;
1188  auto dta = IT.second;
1189  if (!_builder->BuildModel(key, IT.second, FEXPCOMMON_DYNCAST(CFEXPFEInpContBase, ICFEXPDataContIntf, _data_reader(key, dta))))
1190  FEXPCOMMON_EXCEPTION("Error: Macro model building failed!!!");
1191  });
1192  // reschedule model
1193  _builder->ScheduleThreads(ESystemElementType::eNode );
1194  _builder->ScheduleThreads(ESystemElementType::eElement);
1195 }
1196 
1197 //--------------------------------------------------------------------------------------
1198 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
1201 //--------------------------------------------------------------------------------------
1202 {
1203  // 1. get request about sending of current macro model calc. data
1204  auto trkeyset = "trset"; // set transfer data key
1205  auto macro_clc_data = CFEXPDataManager<std::map<std::string, Ptr<t_SerializedData>>>::SafeAllocInstance();
1206  while (true)
1207  {
1208  // 1.1 receive message request for sending respective macro model calc. data ID
1209  auto instruction1 = _net_calc_service.ReadInstruction();
1210  if (is_socket_closed(instruction1))
1211  break;
1212  if (!instruction1->count(t_ENetMessage::eSetMacroModelCalcDataId))
1213  FEXPCOMMON_EXCEPTION("Error: Macro model calculation (set) data ID --> Wrong message!!!");
1214  // macro model data ID
1215  auto requestdata1 = ICFEXPNetClientNodeService::GetReadModelData(instruction1, t_ENetMessage::eSetMacroModelCalcDataId);
1216  if (requestdata1[trkeyset]->empty())
1217  break;
1218  auto model_id = requestdata1[trkeyset]->at(FEXPCOMMON_DEFAULT_INDX);
1219 
1220  // 1.2 read macro model calc. data
1221  auto instruction2 = _net_calc_service.ReadInstruction();
1222  if (is_socket_closed(instruction2))
1223  break;
1224  if (!instruction2->count(t_ENetMessage::eSetMacroModelCalcData))
1225  FEXPCOMMON_EXCEPTION("Error: Macro model calculation (set) data --> Wrong message!!!");
1226  // macro model data
1227  auto requestdata2 = ICFEXPNetClientNodeService::GetReadModelData(instruction2, t_ENetMessage::eSetMacroModelCalcData);
1228  macro_clc_data->insert(MAP_PAIR(model_id, CFEXPDataManager<t_SerializedData>::SafeAllocInstance()));
1229  FEXPCOMMON_FOREACH_ITER_FNC(*requestdata2[trkeyset].get(), { macro_clc_data->at(model_id)->push_back(IT); });
1230  }
1231  if (macro_clc_data->empty())
1232  return;
1233  // load serialized calc data to respective model
1234  FEXPCOMMON_FOREACH_ITER_FNC(*macro_clc_data.get(), { _builder->NetDeserializeStructure(IT.first, IT.second); });
1235 }
1236 
1237 //--------------------------------------------------------------------------------------
1238 template<typename TExpCalc, typename TThreadData, typename TThread, typename Tbarrier>
1240  ::is_socket_closed(Ptr<std::map<size_t, Ptr<t_ModelData>>> data)
1241 //--------------------------------------------------------------------------------------
1242 {
1243  return !_socket_closed ?
1244  _socket_closed = data->count(t_ENetMessage::eError) != FEXPCOMMON_DEFAULT_VALUE :
1245  _socket_closed;
1246 }
1247 
1248 #endif // !_CFEXPSOLVER_H_
void thread_Calculation_function(size_t thread_id, Ptr< TThreadData > data)
Definition: FEXPSolver.h:751
#define HYBRID_PARALLEL_SOLVER_EXCLUDE_THREADS
Definition: FEXPSolver.h:666
#define IT
Definition: FEXPCommon.h:155
#define THREAD_COUNT_UPDATER
Definition: FEXPSolver.h:515
virtual void AddModel(const t_ModelData &data)=0
bool GetIsEnd(size_t thread_id)
Definition: FEXPSolver.h:179
Definition: FEXPSerialization.h:204
static std::string GetDefOrder()
Definition: FEXPCalculationResult.h:95
virtual void End() override
It provides forced ending of a numerical simulation process (not implemented yet).
Definition: FEXPSolver.h:81
Ptr< ICFEXPResultExport > _exporter
Definition: FEXPSolver.h:50
virtual void End()=0
It provides forced ending of a numerical simulation process (not implemented yet).
t_fexpcommon_ct GetTimeStep(size_t thread_id)
Definition: FEXPSolver.h:174
Base setting related to the numerical simulation process.
Definition: FEXPSetting.h:57
Definition: FEXPSerialization.h:45
#define FEXPCOMMON_FOREACH(start, end, index)
Definition: FEXPCommon.h:153
#define FEXPCOMMON_KEY_TABLE_IDNTF
Definition: FEXPCommon.h:182
static std::string GetDefOrder()
Definition: FEXPCalculationResult.h:29
static Ptr< t_SerializedData > GetSerializedBoundingBox(Ptr< t_BoundBox > bb)
Definition: FEXPGeom.cpp:90
#define FEXPCOMMON_STACAST(clsfrom, clsto, variable)
Definition: FEXPCommon.h:137
Base interface of a data provided into each thread.
Definition: FEXPSolver.h:168
virtual Ptr< t_SerializedData > GetSerializedData()=0
virtual void RmvModel(const std::string &key)=0
#define FEXPCOMMON_FOREACH_ITER_FNC(data, lambda_body)
Definition: FEXPCommon.h:157
ICFEXPSolverBase(Ptr< ICFEXPModelBuilderBase > builder, Ptr< ICFEXPResultExport > exporter)
Definition: FEXPSolver.h:27
Base interface for export of results.
Definition: FEXPResultExport.h:19
void SetTimeStep(size_t thread_id, t_fexpcommon_ct value)
Definition: FEXPSolver.h:175
Definition: FEXPDataContainer.h:25
virtual void SetCurrentDt(t_fexpcommon_ct dt)=0
Ptr< t_KD_def_tree< ICFEXPElementNodeBase > > _kd_tree_map
Definition: FEXPSolver.h:48
std::map< size_t, t_fexpcommon_ct > _dt_map
Definition: FEXPSolver.h:187
Definition: FEXPCommon.h:276
t_fexpcommon_ct GetMinTStep()
Definition: FEXPSolver.cpp:47
double t_fexpcommon_ct
Definition: FEXPCommon.h:120
Ptr< ICFEXPModelBuilderBase > _builder
Definition: FEXPSolver.h:49
Base interface for FE nodes.
Definition: FEXPElement.h:245
std::map< size_t, size_t > _time_consistncy_map
Definition: FEXPSolver.h:189
Definition: FEXPSolver.h:67
Definition: FEXPDataContainer.h:25
static Ptr< t_BoundBox > ExtBoundingBox(Ptr< CFEXGeomTools::t_BoundBox > current_bb, t_fexpcommon_ct ratio)
Definition: FEXPGeom.cpp:63
virtual void SetSerializedData(Ptr< t_SerializedData > data)=0
static t_ModelData & GetReadModelData(Ptr< std::map< size_t, Ptr< t_ModelData >>> data, size_t key)
Definition: FEXPNetworkInterface.cpp:9
static Ptr< t_BoundBox > GetBoundingBox(Ptr< CFEXGeomTools::t_BoundBox > current_bb, Ptr< CFEXPFECoordinates< t_fexpcommon_ct >> item_to_check)
Definition: FEXPGeom.cpp:9
#define FEXPCOMMON_DEFAULT_INDX
Definition: FEXPCommon.h:171
Base interface of a solver.
Definition: FEXPSolver.h:24
virtual void Start() override
Definition: FEXPSolver.h:729
Ptr< TThread > get_thread_instance(size_t id, Ptr< TThreadData > data, bool is_calc_thread)
Definition: FEXPSolver.h:738
Definition: FEXPSerialization.h:204
#define FEXPCOMMON_NOT_IMPLEMENTED_EX
Definition: FEXPCommon.h:144
static std::enable_if< std::is_arithmetic< TValue >::value, std::string >::type NumberToString(TValue value)
Definition: FEXPCommon.h:1079
std::map< t_ModelDataKey, Ptr< t_ModelDataDta > > t_ModelData
Definition: FEXPDataContainer.h:15
It stores the result data.
Definition: FEXPCalculationResult.h:132
std::map< size_t, bool > _is_end_map
Definition: FEXPSolver.h:188
#define FEXPCOMMON_DELIMITER
Definition: FEXPCommon.h:180
virtual ~ICFEXPSolverBase()
Definition: FEXPSolver.h:29
#define FEXPCOMMON_EXCEPTION(error_text)
Definition: FEXPCommon.h:143
Definition: FEXPDataContainer.h:25
#define FEXPCOMMON_EMPTY_STRING
Definition: FEXPCommon.h:183
virtual t_fexpcommon_ct GetCurrentDt()=0
#define FEXPCOMMON_FOREACH_ITER(data)
Definition: FEXPCommon.h:156
bool CheckEnd()
Definition: FEXPSolver.cpp:67
void CheckCalcTimeConsistency()
Definition: FEXPSolver.cpp:82
virtual ~CFEXPSolverThreadInputData()
Definition: FEXPSolver.h:207
Base data provided into each thread.
Definition: FEXPSolver.h:202
Definition: FEXPSolver.h:226
Definition: FEXPDataContainer.h:25
static Ptr< TType > SafeAllocInstance(VarArgs &&... inpar)
It allocates data.
Definition: FEXPCommon.h:392
CFEXPSolverThreadInputData(size_t threads)
Definition: FEXPSolver.h:206
#define FEXPCOMMON_KEY_BLOCK_IDNTF
Definition: FEXPCommon.h:181
virtual void Start()=0
It starts process of a numerical simulation.
#define PARALLEL_SOLVER_ERROR_THREADS
Hybrid-parallel solver (Net/CPU/GPU?).
Definition: FEXPSolver.h:671
#define DEFAULT_BB_RATIO
Definition: FEXPGeom.h:469
void SetMinTStep(t_fexpcommon_ct value)
Definition: FEXPSolver.cpp:60
#define MAP_PAIR(key, itm)
Definition: FEXPCommon.h:471
virtual ~ICFEXPThreadDataBase()
Definition: FEXPSolver.h:172
Ptr< std::vector< Ptr< ICFEXPElementNodeBase > > > check_node(const std::vector< t_fexpcommon_ct > &min_bound, const std::vector< t_fexpcommon_ct > &max_bound)
Definition: FEXPSolver.cpp:20
Base interface for system element.
Definition: FEXPDataContainer.h:28
Base container interface.
Definition: FEXPSerializeData.h:601
#define FEXPCOMMON_DEFAULT_VALUE
Definition: FEXPCommon.h:179
void update_topology_map_for_contact()
Definition: FEXPSolver.cpp:10
Network service on the client workstation side.
Definition: FEXPNetworkInterface.h:184
#define RESULT_FILE_STRUCT_BLCS
Definition: FEXPSerialization.h:184
static void WriteLine()
Definition: FEXPCommon.cpp:154
#define RESULT_FILE_STRUCT_TABS
Definition: FEXPSerialization.h:185
Base container interface focused on processing of a serialized/deserialized data. ...
Definition: FEXPSerializeData.h:619
void SetCalcTimeIncrement(size_t thread_id, size_t value)
Definition: FEXPSolver.h:182
Smart pointer.
Definition: FEXPCommon.h:274
static std::string GetCalcBehavOutString(Ptr< ICFEXPElementNodeBase > node, size_t dof)
It composes formated output string for the monitoring of the FEXP solver behaviour.
Definition: FEXPCalculation.cpp:12
#define FEXPCOMMON_DYNCAST(clsfrom, clsto, variable)
Definition: FEXPCommon.h:138
ICFEXPThreadDataBase(size_t threads)
Definition: FEXPSolver.cpp:32
CFEXPHybridParallelSolver(std::function< Ptr< CFEXPFEInpContBase >(std::string &, Ptr< std::vector< std::string >>)> reader, Ptr< ICFEXPModelBuilderBase > builder, std::function< std::string(size_t)> model_key_gttr, ICFEXPNetClientNodeService &net_service)
Definition: FEXPSolver.h:718
Ptr< std::vector< size_t > > GetThreadId()
Definition: FEXPSolver.cpp:99
#define FEXPCOMMON_DFLT_TXT
Definition: FEXPCommon.h:189
void SetIsEnd(size_t thread_id, bool value)
Definition: FEXPSolver.h:180